#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
.doc文件转换为.docx格式的工具模块
支持多种转换方法：Windows COM、LibreOffice、在线转换等
"""

import os
import sys
import subprocess
import tempfile
from pathlib import Path
from typing import Optional, Union
import platform


class DocConverter:
    """Doc文件转换器"""
    
    def __init__(self):
        self.system = platform.system().lower()
        
    def convert_to_docx(self, doc_path: Union[str, Path], output_path: Optional[Union[str, Path]] = None) -> Optional[str]:
        """
        将.doc文件转换为.docx格式
        
        Args:
            doc_path: .doc文件路径
            output_path: 输出.docx文件路径，如果为None则自动生成
            
        Returns:
            转换成功返回.docx文件路径，失败返回None
        """
        doc_path = Path(doc_path)
        
        if not doc_path.exists():
            print(f"错误: 文件 {doc_path} 不存在")
            return None
            
        if not doc_path.suffix.lower() == '.doc':
            print(f"错误: 文件 {doc_path} 不是.doc格式")
            return None
        
        # 生成输出路径
        if output_path is None:
            output_path = doc_path.with_suffix('.docx')
        else:
            output_path = Path(output_path)
        
        # 如果输出文件已存在，直接返回
        if output_path.exists():
            print(f"文件已存在: {output_path}")
            return str(output_path)
        
        # 尝试不同的转换方法
        methods = [
            self._convert_with_win32com,
            self._convert_with_libreoffice,
            self._convert_with_pandoc,
        ]
        
        for method in methods:
            try:
                result = method(doc_path, output_path)
                if result:
                    print(f"转换成功: {doc_path} -> {output_path}")
                    return str(output_path)
            except Exception as e:
                print(f"转换方法 {method.__name__} 失败: {e}")
                continue
        
        print("所有转换方法都失败了")
        return None
    
    def _convert_with_win32com(self, doc_path: Path, output_path: Path) -> bool:
        """使用Windows COM接口转换（需要安装Microsoft Word）"""
        if self.system != 'windows':
            raise Exception("win32com只支持Windows系统")
        
        try:
            import win32com.client as win32
            
            # 创建Word应用程序对象
            word = win32.gencache.EnsureDispatch('Word.Application')
            word.Visible = False
            word.DisplayAlerts = False
            
            try:
                # 打开.doc文件
                doc = word.Documents.Open(str(doc_path.absolute()))
                
                # 保存为.docx格式 (FileFormat=16 表示docx格式)
                doc.SaveAs2(str(output_path.absolute()), FileFormat=16)
                doc.Close()
                
                return True
                
            finally:
                word.Quit()
                
        except ImportError:
            raise Exception("未安装pywin32库，请运行: pip install pywin32")
        except Exception as e:
            raise Exception(f"Word COM转换失败: {e}")
    
    def _convert_with_libreoffice(self, doc_path: Path, output_path: Path) -> bool:
        """使用LibreOffice转换"""
        # 查找LibreOffice可执行文件
        libreoffice_paths = [
            'libreoffice',
            'soffice',
            '/usr/bin/libreoffice',
            '/usr/bin/soffice',
            '/Applications/LibreOffice.app/Contents/MacOS/soffice',
            'C:\\Program Files\\LibreOffice\\program\\soffice.exe',
            'C:\\Program Files (x86)\\LibreOffice\\program\\soffice.exe',
        ]
        
        libreoffice_cmd = None
        for path in libreoffice_paths:
            if self._command_exists(path):
                libreoffice_cmd = path
                break
        
        if not libreoffice_cmd:
            raise Exception("未找到LibreOffice，请安装LibreOffice")
        
        # 创建临时目录用于转换
        with tempfile.TemporaryDirectory() as temp_dir:
            try:
                # LibreOffice转换命令
                cmd = [
                    libreoffice_cmd,
                    '--headless',
                    '--convert-to', 'docx',
                    '--outdir', temp_dir,
                    str(doc_path.absolute())
                ]
                
                # 执行转换
                result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
                
                if result.returncode != 0:
                    raise Exception(f"LibreOffice转换失败: {result.stderr}")
                
                # 查找生成的docx文件
                temp_docx = Path(temp_dir) / f"{doc_path.stem}.docx"
                if not temp_docx.exists():
                    raise Exception("转换后的docx文件未找到")
                
                # 移动到目标位置
                import shutil
                shutil.move(str(temp_docx), str(output_path))
                
                return True
                
            except subprocess.TimeoutExpired:
                raise Exception("LibreOffice转换超时")
            except Exception as e:
                raise Exception(f"LibreOffice转换失败: {e}")
    
    def _convert_with_pandoc(self, doc_path: Path, output_path: Path) -> bool:
        """使用Pandoc转换（可能质量不如其他方法）"""
        if not self._command_exists('pandoc'):
            raise Exception("未找到Pandoc，请安装Pandoc")
        
        try:
            cmd = [
                'pandoc',
                str(doc_path),
                '-o', str(output_path)
            ]
            
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
            
            if result.returncode != 0:
                raise Exception(f"Pandoc转换失败: {result.stderr}")
            
            return output_path.exists()
            
        except subprocess.TimeoutExpired:
            raise Exception("Pandoc转换超时")
        except Exception as e:
            raise Exception(f"Pandoc转换失败: {e}")
    
    def _command_exists(self, command: str) -> bool:
        """检查命令是否存在"""
        try:
            if os.path.isfile(command):
                return True
            result = subprocess.run(['which', command] if self.system != 'windows' else ['where', command], 
                                  capture_output=True, text=True)
            return result.returncode == 0
        except:
            return False
    
    def get_available_methods(self) -> list:
        """获取当前系统可用的转换方法"""
        methods = []
        
        # 检查Windows COM
        if self.system == 'windows':
            try:
                import win32com.client
                methods.append("Windows COM (Microsoft Word)")
            except ImportError:
                pass
        
        # 检查LibreOffice
        if self._command_exists('libreoffice') or self._command_exists('soffice'):
            methods.append("LibreOffice")
        
        # 检查Pandoc
        if self._command_exists('pandoc'):
            methods.append("Pandoc")
        
        return methods


def convert_doc_file(doc_path: str, output_path: str = None) -> Optional[str]:
    """
    便捷函数：转换单个.doc文件
    
    Args:
        doc_path: .doc文件路径
        output_path: 输出路径，可选
        
    Returns:
        成功返回.docx文件路径，失败返回None
    """
    converter = DocConverter()
    return converter.convert_to_docx(doc_path, output_path)


def main():
    """命令行接口"""
    import argparse
    
    parser = argparse.ArgumentParser(description='将.doc文件转换为.docx格式')
    parser.add_argument('input_file', help='输入的.doc文件路径')
    parser.add_argument('-o', '--output', help='输出的.docx文件路径')
    parser.add_argument('--list-methods', action='store_true', help='列出可用的转换方法')
    
    args = parser.parse_args()
    
    converter = DocConverter()
    
    if args.list_methods:
        methods = converter.get_available_methods()
        print("可用的转换方法:")
        for method in methods:
            print(f"  - {method}")
        if not methods:
            print("  没有可用的转换方法")
            print("  请安装以下软件之一:")
            print("    - Microsoft Word + pywin32 (Windows)")
            print("    - LibreOffice")
            print("    - Pandoc")
        return
    
    if not os.path.exists(args.input_file):
        print(f"错误: 文件 {args.input_file} 不存在")
        return
    
    result = converter.convert_to_docx(args.input_file, args.output)
    if result:
        print(f"转换成功: {result}")
    else:
        print("转换失败")


if __name__ == "__main__":
    main()
